<script>
import {Table} from 'ant-design-vue';
import {createPagination, createProps} from '@/utils/CommonUtils';
import TableSelectionInfo from './TableSelectionInfo.vue';
import TableResizeableReander from './TableResizeableReander';
import ColumnsSetting from './ColumnsSetting.vue';

const selectType = {
  multiple: 'multiple',
  single: 'single'
};

export default {
  name: 'HTable',
  provide() {
    return {
      getTableInfo: () => this.getTableInfo()
    };
  },
  model: {
    prop: 'pagination',
    event: 'pageChange'
  },
  props: {
    configurable: createProps(Boolean, true),
    resizeable: createProps(Boolean, true),
    componentKey: createProps(String),
    select: createProps(String, selectType.multiple), // single, multiple
    rowKey: createProps(String, 'id'),
    dataSource: createProps(Array),
    columns: createProps(Array),
    actionWidth: createProps(Number),
    pagination: {
      type: [Object, Boolean],
      default: null
    },
  },
  data() {
    return {
      headerReander: new TableResizeableReander(),
      actionColumn: undefined,
      selectedRowKeys: [],
      selectedRows: [],
      innerColumns: [],
      dataPagination: createPagination(),
      tableLoading: false,
    };
  },
  render(h) {
    return h('div', {
      class: ['h-table', {
        'h-single-select-table': this.select === 'single'
      }]
    }, [
      this.renderBatchAction(h),
      this.select === selectType.multiple && (selectType[this.select] ? this.renderTableSelectionInfo(h) : '') || undefined,
      this.renderTable(h)
    ]);
  },
  methods: {
    getComponentKey() {
      if(this.componentKey) return this.componentKey;
      let count = 10, parent = this, keyStrs = [this.$route.path];
      while (count-- && parent) {
        if (parent && parent.$options._componentTag) {
          keyStrs.push(parent.$options._componentTag);
          let temp = parent.$parent;
          if (temp) {
            keyStrs.push(temp.$children.indexOf(parent) + '');
          }
        }
        parent = parent.$parent;
      }
      keyStrs.push(this.columns.length + '');
      keyStrs = keyStrs.toString();

      return btoa(keyStrs);
    },
    renderBatchAction(h) {
      if (!this.$slots.batchAction) return undefined;
      return h('div', {
        class: ['h-table-batch-action-wrapper']
      }, this.$slots.batchAction);
    },
    loading() {
      this.tableLoading = true;
    },
    loaded() {
      this.tableLoading = false;
    },
    getTableInfo() {
      return {
        actionColumn: this.actionColumn,
        columns: this.columns
      };
    },
    renderTableSelectionInfo(h) {
      return this.$createElement(TableSelectionInfo, {
        props: {
          value: this.selectedRowKeys
        },
        on: {
          change: (v) => this.onSelectChange(v)
        }
      }, [this.configurable && this.createColumnsSetting(h) || undefined]);
    },
    createColumnsSetting(h) {
      return h(ColumnsSetting, {
        props: {
          componentKey: this.getComponentKey(),
          selectedColumns: this.innerColumns,
          colums: this.columns,
        },
        on: {
          change: (innerColumns) => this.innerColumns = innerColumns,
        }
      })
    },
    renderTable(h) {
      this.createActionColumn(h);
      this.resolveDefaultColumn();
      return h(Table, {
        props: this.createProps(),
        attrs: this.createAttrs(),
        on: this.createOn(),
        scopedSlots: {...this.$scopedSlots},
        slots: {...this.$slots}
      }, this.$slots.default);
    },
    resolveDefaultColumn() {
      (this.columns || []).forEach(item => {
        if (!item.align) item.align = 'center';
      });
    },
    createActionColumn(h) {
      for (let i = 0; i < this.columns.length; i++) {
        this.columns[i].columnKey = this.columns[i].dataIndex || `${i}`;
      }

      if (this.columns.find(c => c.dataIndex === 'h_table_column_action')) return;
      let actionSlot = undefined;
      if (!(actionSlot = this.$scopedSlots.action)) return;
      this.columns.push(this.doCreateActionColumn(actionSlot));
    },
    doCreateActionColumn(actionSlot) {
      return this.actionColumn = {
        dataIndex: 'h_table_column_action',
        title: '操作',
        width: this.actionWidth || 200,
        align: 'center',
        scopedSlots: {customRender: 'action'}
      };
    },
    createOn() {
      return {
        ...this.$listeners,
        change: (pagination) => this.pageChange(pagination)
      };
    },
    pageChange(pagination) {
      // if (this.$listeners.pageChange) {
      //   this.tableLoading = true
      // }

      this.innerPagination = pagination;

      // this.$emit('pageChange', {
      //   pagination, loaded: () => this.loaded()
      // })
    },
    createProps() {
      return {
        ...this.$attrs,
        ...this.$props,
        size: 'middle',
        bordered: true,
        loading: this.tableLoading,
        rowSelection: this.createSelection(),
        pagination: this.pagination === false ? false : (this.pagination || this.innerPagination),
        rowKey: this.rowKey,
        columns: this.innerColumns,
        customRow: (record) => this.customRow(record),
        components: this.resizeable && {
          header: {
            cell: (...args) => this.headerReander.render(...args)
          } || undefined
        }
      };
    },
    onSelectChange(selectedRowKeys) {
      if (selectedRowKeys && selectedRowKeys.length > 1 && this.select === 'single') {
        selectedRowKeys = [selectedRowKeys[selectedRowKeys.length - 1]];
      }
      this.selectedRowKeys = selectedRowKeys;
      this.$emit('selectChange', {
        selectedRowKeys,
        selectRows: this.getSelectRows()
      });
    },
    setPagniation(pagination) {
      this.pageChange(pagination);
    },
    clearSelection() {
      this.selectedRowKeys = [];
      this.selectedRows = [];

      this.$emit('selectChange', {
        selectedRowKeys: this.selectedRowKeys,
        selectRows: this.getSelectRows()
      });
    },
    setSelectedRowKeys(selectedRowKeys) {
      this.selectedRowKeys = selectedRowKeys;
      this.getSelectRows();
    },
    getSelectedRowKeys() {
      return this.selectedRowKeys;
    },
    setSelectedRows(selectedRows) {
      this.selectedRows = selectedRows;
    },
    getSelectRows() {
      let selectedRowKeys = this.selectedRowKeys;
      let list = this.selectedRows.filter(row => selectedRowKeys.indexOf(row[this.rowKey]) !== -1);
      selectedRowKeys.forEach(key => {
        if (!list.find(item => item[this.rowKey] === key)) {
          // 在已经选择的id列表里面没有找到, 说明这个key是新加进来的, 那就到dataSource里面找找
          let temp = this.dataSource.find(item => item[this.rowKey] === key);
          temp && list.push(temp);
          if (!temp) {
            // dataSource里面没有找到数据行!
            console.error('选中了一条在dataSource里面不存在的数据行');
          }
        }
      });
      return this.selectedRows = list;
    },
    onSearch() {
      this.clearSelection();
      this.pagination = createPagination();
    },
    customRow(record) {
      return {
        on: {
          click: () => {
            let key = record[this.rowKey];
            if (!this.selectedRowKeys) this.selectedRowKeys = [];
            if (key && selectType[this.select]) {
              if ((this.selectedRowKeys.indexOf(key)) !== -1) {
                if (this.select === selectType.single) {
                  return
                }
                this.selectedRowKeys = this.selectedRowKeys.filter(k => k !== key);

                this.onSelectChange([...this.selectedRowKeys]);
              } else {
                this.onSelectChange([...this.selectedRowKeys, key]);
              }
            }
          }
        }
      };
    },
    createSelection() {
      if (!selectType[this.select]) return null;
      return {
        selectedRowKeys: this.selectedRowKeys || [],
        onChange: (selectedRowKeys) => this.onSelectChange(selectedRowKeys)
      };
    },
    createAttrs() {
      return {
        ...this.$attrs
      };
    }
  },
  computed: {
    innerPagination: {
      get() {
        return this.pagination || this.dataPagination;
      },
      set(v) {
        v = {...v};
        this.dataPagination = v;
        this.$emit('pageChange', {pagination: this.dataPagination, loaded: () => this.loaded()});
      },
    }
  },
  watch: {
    columns: {
      handler() {
        this.headerReander && this.headerReander.setColumns(this.columns);
        this.innerColumns = this.columns
      },
      immediate: true
    },
    select: {
      handler() {
        this.headerReander && this.headerReander.setHasSelect(!!this.createSelection());
      },
      immediate: true
    },
    dataSource: {
      handler() {
        // this.clearSelection()
        if (this.pagination === false) {
          this.innerPagination.total = this.dataSource.length;
        }
      },
      immediate: true
    },
  }
};
</script>
<style>
.h-single-select-table .ant-table-thead .ant-table-selection {
  display: none;
}

.h-table-batch-action-wrapper {
  padding: 10px 0;
}

.h-table-batch-action-wrapper > * {
  margin-right: 10px;
}

.h-table-dragable-cell {
  position: relative;
}

.h-table-dragable-cell-moving-bar {
  height: 100px;
  width: 1px;
  background: #1890ff;
  position: fixed;
  z-index: 1000;
  pointer-events: none;
}

.h-table-dragable-cell-bar {
  position: absolute;
  right: 0;
  width: 5px;
  //background: red;
  height: 100%;
  cursor: col-resize;
  top: 0
}

.h-search-table-batch-action-wrapper > * {
  margin-right: 10px;
}
</style>